package nsu.edu.zsq.service.impl.student;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import nsu.edu.zsq.bean.Status;
import nsu.edu.zsq.bean.StuCourse;
import nsu.edu.zsq.bean.StuCourseExample;
import nsu.edu.zsq.bean.TchCourse;
import nsu.edu.zsq.common.RequestHolder;
import nsu.edu.zsq.dao.StatusMapper;
import nsu.edu.zsq.dao.StuCourseMapper;
import nsu.edu.zsq.dao.TchCourseMapper;
import nsu.edu.zsq.exception.ParamException;
import nsu.edu.zsq.param.PageQuery;
import nsu.edu.zsq.param.TchCourseParam;
import nsu.edu.zsq.service.student.CourseManagerService;
import nsu.edu.zsq.service.sys.SysLogService;

/** 
* Description: 学生课程管理的service实现类<br>
*/
@Service
public class CourseManagerServiceImpl implements CourseManagerService {

    @Autowired
    private StuCourseMapper stuCourseMapper;
    @Autowired
    private TchCourseMapper tchCourseMapper;
    @Autowired
    private SysLogService sysLogService;
    @Autowired
    private StatusMapper statusMapper;
    
    @Override
    public List<StuCourse> listStuCourse() {
        List<StuCourse> listStuCourse = stuCourseMapper.listClassCourse(RequestHolder.getCurrentStudent().getClassId());
        return listStuCourse;
    }

    @Override
    public PageInfo<TchCourseParam> listTchCourse(PageQuery pageQuery) {
        // 检查选课是否开启
        Status status = statusMapper.selectByPrimaryKey(1);
        if (status.getState() == 0) {
            throw new ParamException("不是选课时间");
        }
        
        PageHelper.startPage(pageQuery.getPageNum(),pageQuery.getPageSize());
        List<TchCourseParam> listTchCourse = tchCourseMapper.listTchCourse(RequestHolder.getCurrentStudent().getMajorNo());
        PageInfo<TchCourseParam> pageInfo = new PageInfo<TchCourseParam>(listTchCourse, pageQuery.getNavigatePages());
        return pageInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void chooseCourse(int tchCourseId) {
        TchCourse tchCourse = tchCourseMapper.selectByPrimaryKey(tchCourseId);
        // 检查是否重复选择同一门课
        if (checkCourseExist(tchCourseId)) {
            throw new ParamException("该课程已存在");
        }
        // 检查是否与该学生课程时间冲突
        if (checkTimeConflict(tchCourse)) {
            throw new ParamException("该课程与你的课程时间冲突");
        }
        // 检查课程人数是否已满
        if (checkStuNumberEnough(tchCourse)) {
            throw new ParamException("该课程人数已满");
        }
        
        StuCourse after = StuCourse.builder().stuNo(RequestHolder.getCurrentStudent().getStuNo()).tchCourseId(tchCourseId)
                .courseNo(tchCourse.getCourseNo()).courseName(tchCourse.getCourseName()).courseType(tchCourse.getCourseType())
                .startDay(tchCourse.getStartDay()).startTime(tchCourse.getStartTime()).roomName(tchCourse.getRoomName())
                .teacherName(tchCourse.getTeacherNo()).operator(RequestHolder.getCurrentStudent().getStuNo())
                .operatorTime(new Date()).build();
        stuCourseMapper.insertSelective(after);
        
        // 添加日志
        String instruction = "课程管理-网上选课";
        sysLogService.saveSysLogByStudent(null, after, instruction);
        
    }
    
    /**
     * 检查该选修课是否已经存在于学生课表中
     * @param tchCourseId 教师课程id
     * @return boolean true：存在 false：不存在
     */
    private boolean checkCourseExist(int tchCourseId) {
        StuCourseExample example = new StuCourseExample();
        example.createCriteria().andStuNoEqualTo(RequestHolder.getCurrentStudent().getStuNo())
            .andTchCourseIdEqualTo(tchCourseId);
        return stuCourseMapper.countByExample(example) > 0;
    }
    
    /**
     * 检查新的选修课是否与学生课程时间安排冲突
     * @param tchCourse 教师课程信息
     * @return boolean true：冲突 false：不冲突
     */
    private boolean checkTimeConflict(TchCourse tchCourse) {
        StuCourseExample example = new StuCourseExample();
        example.createCriteria().andStuNoEqualTo(RequestHolder.getCurrentStudent().getStuNo())
            .andStartDayEqualTo(tchCourse.getStartDay()).andStartTimeEqualTo(tchCourse.getStartTime());
        return stuCourseMapper.countByExample(example) > 0;
    }

    /**
     * 检查该选修课程人数是否已满
     * @param tchCourse 教师课程信息
     * @return boolean true：人数已满 false：人数未满
     */
    private boolean checkStuNumberEnough(TchCourse tchCourse) {
        StuCourseExample example = new StuCourseExample();
        example.createCriteria().andTchCourseIdEqualTo(tchCourse.getId());
        return stuCourseMapper.countByExample(example) >= tchCourse.getStuNumber();
    }

    @Override
    public List<HashMap<String, String>> listStuChooseCourse() {
        List<HashMap<String, String>> listStuCourse = stuCourseMapper.listStuChooseCourse(RequestHolder.getCurrentStudent().getStuNo());
        return listStuCourse;
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeChooseCourse(int stuCourseId) {
        // 检查选课是否开启
        Status status = statusMapper.selectByPrimaryKey(1);
        if (status.getState() == 0) {
            throw new ParamException("不是选课时间，无法进行退选操作");
        }
        
        StuCourse before = stuCourseMapper.selectByPrimaryKey(stuCourseId);
        stuCourseMapper.deleteByPrimaryKey(stuCourseId);
        
        // 添加日志
        String instruction = "课程管理-选课结果-退选";
        sysLogService.saveSysLogByStudent(before, null, instruction);
    }
}
